package com.dashboard.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class TestFuture {
	
	/*
	 * Runnable不会返回结果
	 * Callable功能更强大一些，被线程执行后，可以返回值，这个返回值可以被Future拿到，也就是说，Future可以拿到异步执行任务的返回值.
	 */
	public static class Task implements Callable<String> {
	    @Override
	    public String call() throws Exception {
	        String tid = String.valueOf(Thread.currentThread().getId());
	        Thread.sleep(2000);
	        System.out.printf("Thread#%s : in call\n", tid);
	        return tid;
	    }
	}
	
	
	public static void callableAndFuture() {
		Callable<String> callable = new Task();
		/*  
		 * FutureTask实现了两个接口，Runnable和Future，
		 * 所以它既可以作为Runnable被线程执行，又可以作为Future得到Callable的返回值
		 */
		FutureTask<String> future = new FutureTask<String>(callable);
		new Thread(future).start();
		try {
			Thread.sleep(5000);// 可能做一些事情
			System.out.println(future.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
		
	
	/*
	 * 其实也可以不使用CompletionService，可以先创建一个装Future类型的集合，
	 * 用Executor提交的任务返回值添加到集合中，最后遍历集合取出数据
	 */
	public static void completionServiceAndFuture(){
		ExecutorService threadPool = Executors.newCachedThreadPool();
		CompletionService<String> cs = new ExecutorCompletionService<String>(threadPool);
		for(int i = 1; i < 5; i++) {
			cs.submit(new Task());
		}
		// 可能做一些事情
		try {
			for(int i = 1; i < 5; i++) {
				System.err.println(cs.take().get());
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void executorServiceAndFuture(){
        List<Future<String>> results = new ArrayList<Future<String>>();
        ExecutorService es = Executors.newCachedThreadPool();  //ExecutorService继承自Executor
        for(int i=0; i<5;i++)
            results.add(es.submit(new Task()));  //添加到集合中，最后遍历集合取出数据
       
		try {
			 for(Future<String> res : results)
				 System.out.println(res.get());
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    	System.out.println(Runtime.getRuntime().availableProcessors());
    	callableAndFuture();
    	completionServiceAndFuture();
    	executorServiceAndFuture();
    }
    
}
